页面效果:

h5_editor.gif

主要解决两个问题:

  • 组件的拖拽;
  • 渲染组件 component 和样式修改组件 styleComponent 数据流转问题。

# 组件的拖拽和克隆

组件拖拽这里使用到的是这个基于 sortable.js (opens new window),使用 Vue 进行封装的组件 Vue.Draggable (opens new window)。具体使用官方文档和相关例子都很详细。

主要使用两个功能:

  • 拖拽:更改页面布局
  • 克隆:将左边渲染组件列表中的组件拖拽克隆到中间页面预览区域

# 拖拽

h5-editor 组件使用方式:

<h5-editor v-model="jsonData" :data="data"></h5-editor>

<template>
    <draggable
        class="dragArea list-group"
        v-model="layout"
        tag="div"
        v-bind="dragOptions"
        @start="startDragLayout"
        @end="finishDragLayout"
        group="preview"
        >
        <div v-for="(element, index) in layout" :key="index">
    		// ...
            <component :is="element.component" :dynamicStyle="element.dynamicStyle"></component>
    	</div>   
    </draggable>
</template>

<script>
export default {
    model: {
        prop: "jsonData",
        event: "changePageInfo",
     },
    props: {
        // 页面初始化数据
        data: {
            type: Array,
            default: () => [],
        },
    },
	data() {
        return {
            layout: []   
        }
    },
    computed: {
        // 主要是定义一些属性
        dragOptions() {
            return {
                animation: 200, // 动画执行时间
                group: "preview", // 这个 group  的作用是,设置渲染区域的 group 和左边组件列表的 group 相同,在同一 group 中,即可进行克隆
                disabled: false,
                ghostClass: "ghost", // 组件拖动还未放下的样式
            };
        },
    },
    // ... 其他实现细节忽略
    watch: {
        // ...
    }
}
</script>

实现 v-model,监听 layout 是否变更,然后派发 changePageInfo 事件即可实现 v-model。

<draggable></draggable> 标签是 Vue.Draggable (opens new window) 封装好的组件,只要把我们的布局数组 layout 跟内部进行判定,即可实现拖拽和 layout 数据更新。

<draggable></draggable>标签内部通过一个 v-for循环包裹,结合 Vue 动态组件 <component :is="" /> 即可实现组件的展示。

注:@start@end等事件的绑定,函数的参数里面有新旧索引等重要信息可利用。

# 克隆

h5-editor 组件使用方式:

<h5-editor v-model="jsonData" :data="data"></h5-editor>
<draggable
    class="all-coms__box dragArea list-group"
    :list="baseComponentsData"
    :group="{ name: 'preview', pull: 'clone', put: false }"
    :clone="clone"
    :sort="false"
    @end="finishClone"
>
</draggable>

克隆组件跟拖拽组件多了两个设置属性:

  • group:设置组别,组别跟预览区域的组别一样,都是 preview;
  • sort:禁止自身列表重新排序。

# 显示对应的样式修改组件

在中间预览区域点击一个组件后,右边样式修改区域会显示对应的组件。这个逻辑实现比较简单,因为每个组件都有对应的索引,通过对应索引显示对应组件即可,结合 Vue 动态组件 <component :is="" /> 即可实现组件的展示。

# 修改对应的渲染组件样式

当样式修改组件向上派发事件 changeStyle,父组件 h5-editor 就可以监听到事件触发和携带新的样式对象,然后通过修改 layout 对应索引的 dynamicStyle 属性值($set()触发),即可修改对应渲染组件样式。